package config

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"gitee.com/war2001/NiuMaEasyGo/config"
	"gitee.com/war2001/NiuMaEasyGo/global"
	"github.com/fsnotify/fsnotify"
	"gopkg.in/yaml.v3"
)

// 默认配置文件路径
const DefaultConfigPath = "config.yaml"

var (
	instance *Config
	once     sync.Once
)

// Config 配置管理模块
type Config struct {
	sync.RWMutex
	configFile string
	watcher    *fsnotify.Watcher
}

// Init 初始化配置（单例模式）
func Init() error {
	var err error
	once.Do(func() {
		instance = &Config{
			configFile: DefaultConfigPath,
		}
		err = instance.loadConfig()
		if err == nil {
			err = instance.watchConfig()
		}
	})
	return err
}

// InitWithPath 使用指定路径初始化配置
func InitWithPath(configPath string) error {
	var err error
	once.Do(func() {
		instance = &Config{
			configFile: configPath,
		}
		err = instance.loadConfig()
		if err == nil {
			err = instance.watchConfig()
		}
	})
	return err
}

// GetInstance 获取配置管理实例
func GetInstance() *Config {
	if instance == nil {
		panic("配置未初始化，请先调用 config.Init()")
	}
	return instance
}

// 内部加载配置方法
func (c *Config) loadConfig() error {
	c.Lock()
	defer c.Unlock()

	// 检查配置文件是否存在
	if _, err := os.Stat(c.configFile); os.IsNotExist(err) {
		return fmt.Errorf("配置文件不存在: %s", c.configFile)
	}

	// 读取配置文件
	yamlFile, err := ioutil.ReadFile(c.configFile)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 解析配置文件
	appConfig := &config.AppConfig{}
	err = yaml.Unmarshal(yamlFile, appConfig)
	if err != nil {
		return fmt.Errorf("解析配置文件失败: %v", err)
	}

	// 设置全局配置
	global.Config = appConfig

	// 打印配置加载成功信息
	fmt.Printf("配置文件加载成功: %s\n", c.configFile)
	fmt.Printf("应用名称: %s, 版本: %s, 运行模式: %s\n",
		appConfig.App.Name, appConfig.App.Version, appConfig.App.Mode)

	return nil
}

// 内部监听配置文件变更方法
func (c *Config) watchConfig() error {
	// 创建文件监听器
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return fmt.Errorf("创建文件监听器失败: %v", err)
	}
	c.watcher = watcher

	// 启动监听协程
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				// 配置文件写入事件
				if event.Op&fsnotify.Write == fsnotify.Write {
					fmt.Printf("配置文件已更改: %s\n", event.Name)
					// 重新加载配置
					time.Sleep(100 * time.Millisecond) // 等待文件写入完成
					if err := c.loadConfig(); err != nil {
						fmt.Printf("重新加载配置失败: %v\n", err)
					}
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				fmt.Printf("配置监听错误: %v\n", err)
			}
		}
	}()

	// 获取配置文件的绝对路径
	absPath, err := filepath.Abs(c.configFile)
	if err != nil {
		return fmt.Errorf("获取配置文件绝对路径失败: %v", err)
	}

	// 监听配置文件
	err = watcher.Add(absPath)
	if err != nil {
		return fmt.Errorf("添加配置文件监听失败: %v", err)
	}

	fmt.Printf("开始监听配置文件变更: %s\n", absPath)
	return nil
}

// StopWatch 停止监听配置文件变更
func (c *Config) StopWatch() {
	if c.watcher != nil {
		c.watcher.Close()
	}
}

// GetMode 获取应用运行模式
func (c *Config) GetMode() string {
	c.RLock()
	defer c.RUnlock()
	return global.Config.App.Mode
}

// IsDevMode 是否为开发模式
func (c *Config) IsDevMode() bool {
	return c.GetMode() == "development"
}

// IsProdMode 是否为生产模式
func (c *Config) IsProdMode() bool {
	return c.GetMode() == "production"
}

// IsTestMode 是否为测试模式
func (c *Config) IsTestMode() bool {
	return c.GetMode() == "test"
}

// Shutdown 关闭配置管理
func Shutdown() {
	if instance != nil {
		instance.StopWatch()
	}
}

// StorageConfig 存储配置
type StorageConfig struct {
	Provider     string             `yaml:"provider"`      // 存储提供商: local, oss, cos, qiniu
	UploadDir    string             `yaml:"upload_dir"`    // 上传目录
	URLPrefix    string             `yaml:"url_prefix"`    // URL前缀
	MaxSize      int64              `yaml:"max_size"`      // 最大文件大小
	AllowedTypes []string           `yaml:"allowed_types"` // 允许的文件类型
	ImageProcess ImageProcessConfig `yaml:"image_process"` // 图片处理
	Local        LocalStorageConfig `yaml:"local"`         // 本地存储配置
	OSS          OSSStorageConfig   `yaml:"oss"`           // 阿里云OSS配置
	COS          COSStorageConfig   `yaml:"cos"`           // 腾讯云COS配置
	Qiniu        QiniuStorageConfig `yaml:"qiniu"`         // 七牛云配置
}

// ImageProcessConfig 图片处理配置
type ImageProcessConfig struct {
	Enable    bool            `yaml:"enable"`     // 是否启用
	MaxWidth  int             `yaml:"max_width"`  // 最大宽度
	MaxHeight int             `yaml:"max_height"` // 最大高度
	Quality   int             `yaml:"quality"`    // 图片质量
	Watermark WatermarkConfig `yaml:"watermark"`  // 水印配置
}

// WatermarkConfig 水印配置
type WatermarkConfig struct {
	Enable   bool   `yaml:"enable"`    // 是否启用
	Text     string `yaml:"text"`      // 水印文字
	FontSize int    `yaml:"font_size"` // 字体大小
	Color    string `yaml:"color"`     // 颜色
	Position string `yaml:"position"`  // 位置
}

// LocalStorageConfig 本地存储配置
type LocalStorageConfig struct {
	RootPath   string `yaml:"root_path"`   // 根路径
	BaseURL    string `yaml:"base_url"`    // 基础URL
	CreatePath bool   `yaml:"create_path"` // 是否自动创建路径
}

// OSSStorageConfig 阿里云OSS配置
type OSSStorageConfig struct {
	AccessKeyID     string `yaml:"access_key_id"`     // 访问密钥ID
	AccessKeySecret string `yaml:"access_key_secret"` // 访问密钥密钥
	Endpoint        string `yaml:"endpoint"`          // OSS服务的访问域名
	Bucket          string `yaml:"bucket"`            // 存储空间名称
	BaseURL         string `yaml:"base_url"`          // 自定义域名（可选）
	PathPrefix      string `yaml:"path_prefix"`       // 路径前缀（可选）
	IsPublic        bool   `yaml:"is_public"`         // 是否公开访问
}

// COSStorageConfig 腾讯云COS配置
type COSStorageConfig struct {
	SecretID   string `yaml:"secret_id"`   // 密钥ID
	SecretKey  string `yaml:"secret_key"`  // 密钥
	Region     string `yaml:"region"`      // 地域
	Bucket     string `yaml:"bucket"`      // 存储桶名称
	BaseURL    string `yaml:"base_url"`    // 自定义域名（可选）
	PathPrefix string `yaml:"path_prefix"` // 路径前缀（可选）
	IsPublic   bool   `yaml:"is_public"`   // 是否公开访问
}

// QiniuStorageConfig 七牛云配置
type QiniuStorageConfig struct {
	AccessKey  string `yaml:"access_key"`  // 访问密钥
	SecretKey  string `yaml:"secret_key"`  // 密钥
	Bucket     string `yaml:"bucket"`      // 存储空间名称
	Domain     string `yaml:"domain"`      // 域名
	PathPrefix string `yaml:"path_prefix"` // 路径前缀（可选）
	IsPublic   bool   `yaml:"is_public"`   // 是否公开访问
}
